<template>
  <div style="margin: -20px; position: relative;">
    <div class="node-list" ref="dnd">
      <a @mousedown="e => dragNode(e, 'event', 'start')">开始</a>
      <a @mousedown="e => dragNode(e, 'event', 'end')">结束</a>
      <a @mousedown="e => dragNode(e, 'gateway')">网关</a>
      <a @mousedown="e => dragNode(e, 'activity')">用户任务</a>
    </div>
    <div class="btn-list">
      <el-button @click="submitProcess">保存</el-button>
    </div>
    <el-dropdown ref="menu" @command="handleCommand" placement="bottom-start" class="context-menus" :style="position">
      <i></i>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item v-for="i in menuList" v-bind="i">{{ i.label }}</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
    <div ref="container" style="height: calc(100vh - 65px);"></div>
    <dialogForm ref="form" @submit="onSubmit" />
  </div>
</template>

<script>
import { Graph, Shape } from '@antv/x6'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Dnd } from '@antv/x6-plugin-dnd'
import dialogForm from '@/views/commonBizTable/components/dialogForm'
import { showPorts } from './register/ports'
import http from '@/utils/request'
import { processValidator, addNoddd } from './utils'
import createEdge from './register/edge'
import './register/event'
import './register/gateway'
import './register/activity'
import './register/custom'
export default {
  components: {
    dialogForm
  },
  data() {
    return {
      dnd: null,
      graph: null,
      currentNode: null,
      position: '',
      menuList: [
        { command: 'edit', icon: 'el-icon-edit', label: '编辑', disabled: false },
        { command: 'gateway', icon: 'el-icon-circle-plus-outline', label: '添加网关节点', disabled: false },
        { command: 'activity', icon: 'el-icon-circle-plus-outline', label: '添加用户任务', disabled: false },
        { command: 'start', icon: 'el-icon-circle-plus-outline', label: '添加开始', disabled: false },
        { command: 'end', icon: 'el-icon-circle-plus-outline', label: '添加结束', disabled: false },
        { command: 'del', icon: 'el-icon-delete', label: '删除', disabled: false }
      ]
    }
  },
  mounted() {
    this.initGraph()
    this.initPlugins()
    this.initEvent()
    this.getData()
  },
  watch: {
    $route() {
      console.log('xxxx')
    }
  },
  methods: {
    async submitProcess() {
      await processValidator(this.graph)
      console.log(this.graph.toJSON())
      console.log('正在保存流程数据')
    },
    initGraph() {
      this.graph = new Graph({
        grid: { visible: true },
        connecting: {
          router: 'orth',
          // connector: 'rounded',
          anchor: 'center',
          targetAnchor: 'center',
          sourceAnchor: 'center',
          findParent: 'center',
          snap: { anchor: 'center', radius: 50 },
          allowLoop: false,
          allowBlank: false,
          createEdge
        },
        mousewheel: {
          enabled: true,
          zoomAtMousePosition: true,
          modifiers: 'ctrl',
          minScale: 0.5,
          maxScale: 3,
        },
        panning: { enabled: true, eventTypes: ['leftMouseDown', 'mouseWheel'] },
        background: { color: '#F2F7FA' },
        container: this.$refs.container,
      })
    },
    initPlugins() {
      this.dnd = new Dnd({
        scaled: false,
        target: this.graph,
        dndContainer: this.$refs.dnd
      });
      this.graph.use(new Snapline({ enabled: true }))
    },
    initEvent() {
      this.graph.on('node:mouseenter', ({ e, node }) => {
        showPorts(node, true)
      })
      this.graph.on('node:mouseleave', ({ e, node }) => {
        showPorts(node, false)
      })
      this.graph.on('edge:click', ({ e, edge }) => {
        edge.addTools({ name: 'button-remove' })
      });
      this.graph.on('node:contextmenu', async ({ e, node }) => {
        if (node.shape === 'event') {
          this.menuList = this.menuList.map(i => ({ ...i, disabled: i.label === '编辑' }))
        } else {
          this.menuList = this.menuList.map(i => ({ ...i, disabled: false }))
        }
        this.currentNode = node;
        this.position = `left: ${e.clientX}px;top: ${e.clientY}px;`
        await this.$nextTick()
        this.$refs.menu.handleClick();
      });
      this.graph.on('edge:connected', ({ edge, isNew }) => {
        if (isNew) {
          const { source, target } = edge
          this.graph.removeEdge(edge.id)
          this.graph.addEdge(this.graph.createEdge({ shape: 'bpmn-edge', source: source.cell, target: target.cell }))
        }
      })
    },
    handleCommand(cmd) {
      if (cmd === 'edit') {
        this.editNode()
      } else if (cmd === 'del') {
        const { cells } = this.graph.toJSON();
        const item = cells.find(i =>i?.data?.target === this.currentNode.id)
        this.graph.removeNode(this.currentNode.id)
        if (item) this.graph.removeNode(item.id)
      }
    },
    onSubmit(form) {
      const { label } = form
      this.currentNode.setData(form)
      this.currentNode.setLabel(label)
    },
    editNode() {
      const { data = {} } = this.currentNode.store.data
      this.$refs.form.edit(data, {
        fields: [
          {
            "prop": "label",
            "label": "节点名称",
            "type": "input",
            required: true
          },
          {
            "prop": "name",
            "label": "节点英文名称",
            "type": "input",
            required: true
          },
          {
            "prop": "user",
            "label": "任务处理用户",
            "type": "select",
            required: true,
            "options": [
              { value: 'xxx', label: '小明' },
              { value: 'cccc', label: '小hu' }
            ]
          }
        ]
      })
    },
    dragNode(e, shape, type = '') {
      const nodeList = this.graph.toJSON();
      const startNode = nodeList.cells.find((i) => i.type === 'start');
      const endNode = nodeList.cells.find((i) => i.type === 'end');
      if (type === 'start' && startNode) return;
      if (type === 'end' && endNode) return;
      const labels = { activity: '用户任务', eventstart: '开始', eventend: '结束' }
      let option = { shape, type, label: labels[shape + type] }
      this.dnd.start(this.graph.createNode(option), e);
    },
    async getData() {
      const res = await http.get('data/bpmn.json')
      const cells = []
      res.data.forEach(item => {
        if (item.shape === 'bpmn-edge') {
          cells.push(this.graph.createEdge(item))
        } else if (item.data) {
          const { label } = item.data
          cells.push(this.graph.createNode({ ...item, label }))
        } else {
          cells.push(this.graph.createNode(item))
        }
      })
      this.graph.resetCells(cells)
      this.graph.zoomToFit({ padding: 10, maxScale: 1 })
      // this.graph.fromJSON(graphData);
    },
  }
}
</script>
<style>
.x6-edge {
  position: relative;
  z-index: 1;
}

.x6-node {
  position: relative;
  z-index: 10;
}
</style>
<style lang="scss" scoped>
.node-list {
  position: absolute;
  z-index: 100;
  left: 20px;
  top: 20px;
  user-select: none;

  a {
    cursor: move;
    border-radius: 10px;
    font-size: 12px;
    width: 60px;
    line-height: 30px;
    display: block;
    text-align: center;
    border: #5F95FF 2px solid;
    margin-bottom: 10px;
  }
}

.btn-list {
  position: absolute;
  z-index: 100;
  right: 20px;
  top: 20px;
}

.context-menus {
  position: fixed;
}
</style>